//Britable for iTunes
//MAC AND WINDOWS

//Acknowledgements:
//fjens' code to use AppleScript from Processing (http://processing.org/discourse/yabb2/YaBB.pl?num=1201876176)
//Adrian C for his 5x5 pixel rounded font (http://www.adriantnt.net/pixel_fonts/) NEEDED for rendering the texts on screen
//varacalli for the VBS code used as a starting point for the system (http://www.varacalli.com/random-traffic/2007-08-28-windows-script-itunes-rate-current-track.htm)

//The code gets the track and artist info from iTunes using a shell script (Yes, there should be a better way, but I've been unable to make the "com.apple.cocoa.foundation.* method" to work.
//Then it draws it on screen, a small version and the britable version (the big rectangles) You can watch it here.
//The code could be optimized. It's a smaller version from another sketch which uses anti-alisaing, but with only 25 pixels, there is no improvement.
//So, once the code gets the 25 pixels, it sends them via serial port.
//Processing only calls the shell script once the smaller text is out of the screen, it's a slow operation (100ms) and calling it more frequently would make the animation choppy.
//Project homepage: http://code.google.com/p/britable/
//Project blog (in Spanish): http://www.neuronasmuertas.com/britable/
//
//History
//2009-11-20: Added OS detection and Windows support / Minor text corrections
//2009-11-15: Initial release
import processing.serial.*;

int iFilas = 5;
int iColumnas = 5;
int iAncho = 64;

String sText, sLastText="";
int iTextX = iColumnas;
int iTextY, iTextW;
byte[] bValues = new byte[1+iFilas*iColumnas];

Serial sPort;
boolean bIsWindows = false;

void setup(){

  size(iColumnas*iAncho, (iFilas+1)*iAncho, P2D);
  frameRate(7);
  rectMode(CORNER);
  textFont(createFont("5x5 rounded",8 ,false));
  textMode(SCREEN);
  textAlign(LEFT, TOP);   

  println(Serial.list());
  String portName = Serial.list()[1];
  sPort = new Serial(this, portName, 57600);  

  bValues[0]=111;
  bIsWindows =  System.getProperty("os.name").indexOf("Windows") >= 0;

  println(System.getProperty("os.name") + " bIsWindows=" +  bIsWindows); 

  leeItunes();
}

void leeItunes(){

  sText = "";

  if (bIsWindows) {

    java.io.File folder = new java.io.File(dataPath(""));

    try {
      Process p = Runtime.getRuntime().exec("cscript //Nologo \""+folder.getAbsolutePath()+"/iTunesCurrentTrack.vbs\"");
      BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
      String line;
      while ((line = input.readLine()) != null) {
        sText += line;
      }
      input.close();

    }
    catch(Exception e){
      e.printStackTrace();
    }    

  } 
  else {  
    Vector v = shellExec("osascript -e \"tell application \\\"iTunes\\\"\" -e \"if player state is playing then\" -e \"set output to artist of current track & \\\" - \\\" & name of current track\" -e \"end if\"  -e \"end tell\"");
    sText = v.size() > 0 ? (String)v.get(0) : "Pon en marcha el iTunes, majo";  
  }

  if (!sText.equals(sLastText)) {
    iTextY = iAncho*iFilas + 20;
    iTextW = (int)textWidth(sText);
    sLastText = sText;
  }
  iTextX = iColumnas;

}

void draw() {

  background(0);
  text(sText,iTextX,iTextY);    
  drawText();

  sPort.write(bValues);

  if (--iTextX < -iTextW - 20) leeItunes();

}


void drawText(){
  loadPixels();
  noStroke();  
  fill(255);          
  for (int y=0; y<iFilas;y++){    
    for (int x=0; x<iColumnas;x++){
      if ((pixels[(iTextY+y)*width + x] & 0xff) > 0) {
        bValues[y*iColumnas+x+1] = 1;
        rect(x*iAncho, y*iAncho, iAncho, iAncho);        
      } 
      else {
        bValues[y*iColumnas+x+1] = 0;
      }
    }
  }  
  stroke(200,40,0);        
  noFill();
  rect(0, iTextY, iColumnas-1, iFilas-1);                  
}

Vector shellExec ( String command )
{
  return shellExec ( new String[]{ 
    "/bin/bash", "-c", command         } 
  );
}

Vector shellExec ( String[] command )
{
  Vector lines = new Vector();
  try {
    Process process = Runtime.getRuntime().exec ( command );

    BufferedReader inBufferedReader  = new BufferedReader( new InputStreamReader ( process.getInputStream() ) );
    BufferedReader errBufferedReader = new BufferedReader( new InputStreamReader ( process.getErrorStream() ) );

    String line, eline;
    while ( (line  = inBufferedReader.readLine() ) != null && !errBufferedReader.ready() )
    {
      lines.add(line);
    }
    if ( errBufferedReader.ready() ) {
      while ( (eline  = errBufferedReader.readLine() ) != null )
      {
        println( eline );
      }
      return null;
    }
    int exitVal = process.waitFor();

    inBufferedReader.close();  
    process.getInputStream().close();
    errBufferedReader.close(); 
    process.getErrorStream().close();
  }
  catch (Exception e)
  {
    e.printStackTrace();
    return null;
  }

  return lines;
}




